package com.work.util;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * @author: YanL
 * @createTime: 2022-12-29  10:53
 * @version: 1.0.0
 */
@Slf4j
public class BigDecimalUtil {

  /**
   * 格式化字符串
   */
  private static final String FORMAT_STRING = "#.00";

  /**
   * 保留后两位小数 初始化0.00
   */
  private static final String ZERO_FORMAT_STRING = "0.00";

  /**
   * 字符串 0
   */
  private static final String ZERO = "0";


  /**
   * 传入字符串转为BigDecimal对象对比大小(-1 => b1 < b2)(0 => b1 = b2)(1 => b1 > b2)
   *
   * @param b1 字符串
   * @param b2 字符串
   * @return 比较结果
   */
  public static int compareBigDecimal(String b1, String b2) {
    return new BigDecimal(b1).compareTo(new BigDecimal(b2));
  }

  /**
   * 传入BigDecimal对象对比大小(-1 => b1 < b2)(0 => b1 = b2)(1 => b1 > b2)
   *
   * @param b1 BigDecimal对象
   * @param b2 BigDecimal对象
   * @return 比较结果
   */
  public static int compareBigDecimal(BigDecimal b1, BigDecimal b2) {
    return b1.compareTo(b2);
  }

  /**
   * 保留后两位小数
   *
   * @param obj BigDecimal对象
   * @return 处理结果
   */
  public static String formatKeepLast2Number(BigDecimal obj) {
    DecimalFormat df = new DecimalFormat(FORMAT_STRING);
    if (compareBigDecimal(obj, BigDecimal.ZERO) == 0) {
      return ZERO_FORMAT_STRING;
    } else if (compareBigDecimal(obj, BigDecimal.ZERO) > 0 && compareBigDecimal(obj, new BigDecimal(1)) < 0) {
      return "0" + String.valueOf(df.format(obj));
    } else {
      return df.format(obj);
    }
  }

  /**
   * BigDecimal精确的加法运算
   *
   * @param o1    加数
   * @param o2    加数
   * @param scale 保留小数点位数
   * @return 两数之和
   */
  public static String add(Object o1, Object o2, int scale) throws Exception {
    if (scale < 0) {
      throw new IllegalArgumentException("scale必须大于或者等于0");
    }
    if (o1 instanceof String && o2 instanceof String) {
      // o1和o2均是字符串类型
      return objToString(new BigDecimal(objToString(o1)).add(new BigDecimal(objToString(o2))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Long && o2 instanceof Long) {
      // o1和o2均是Long类型
      return objToString(new BigDecimal(Long.parseLong(objToString(o1))).add(new BigDecimal(Long.parseLong(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Double && o2 instanceof Double) {
      // o1和o2均是Double类型
      return objToString(BigDecimal.valueOf(Double.parseDouble(objToString(o1))).add(BigDecimal.valueOf(Double.parseDouble(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else {
      log.error("o1的类型为:{} o2的类型为:{}", objToString(o1.getClass()), objToString(o2.getClass()));
      throw new RuntimeException("o1与o2类型不一致");
    }
  }

  /**
   * BigDecimal精确的减法运算
   *
   * @param o1    减数
   * @param o2    被减数
   * @param scale 保留小数点位数
   * @return 两数之差
   */
  public static String sub(Object o1, Object o2, int scale) throws Exception {
    if (scale < 0) {
      throw new IllegalArgumentException("scale必须大于或者等于0");
    }
    if (o1 instanceof String && o2 instanceof String) {
      // o1和o2均是字符串类型
      return objToString(new BigDecimal(objToString(o1)).subtract(new BigDecimal(objToString(o2))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Long && o2 instanceof Long) {
      // o1和o2均是Long类型
      return objToString(new BigDecimal(Long.parseLong(objToString(o1))).subtract(new BigDecimal(Long.parseLong(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Double && o2 instanceof Double) {
      // o1和o2均是Double类型
      return objToString(BigDecimal.valueOf(Double.parseDouble(objToString(o1))).subtract(BigDecimal.valueOf(Double.parseDouble(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else {
      log.error("o1的类型为:{} o2的类型为:{}", objToString(o1.getClass()), objToString(o2.getClass()));
      throw new RuntimeException("o1与o2类型不一致");
    }
  }

  /**
   * BigDecimal精确的乘法运算
   *
   * @param o1    乘数
   * @param o2    乘数
   * @param scale 保留小数点位数
   * @return 两数之积
   */
  public static String mul(Object o1, Object o2, int scale) throws Exception {
    if (scale < 0) {
      throw new IllegalArgumentException("scale必须大于或者等于0");
    }
    if (o1 instanceof String && o2 instanceof String) {
      // o1和o2均是字符串类型
      return objToString(new BigDecimal(objToString(o1)).multiply(new BigDecimal(objToString(o2))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Long && o2 instanceof Long) {
      // o1和o2均是Long类型
      return objToString(new BigDecimal(Long.parseLong(objToString(o1))).multiply(new BigDecimal(Long.parseLong(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else if (o1 instanceof Double && o2 instanceof Double) {
      // o1和o2均是Double类型
      return objToString(BigDecimal.valueOf(Double.parseDouble(objToString(o1))).multiply(BigDecimal.valueOf(Double.parseDouble(objToString(o2)))).setScale(scale, RoundingMode.HALF_UP));
    } else {
      log.error("o1的类型为:{} o2的类型为:{}", objToString(o1.getClass()), objToString(o2.getClass()));
      throw new RuntimeException("o1与o2类型不一致");
    }
  }

  /**
   * BigDecimal精确的除法运算
   *
   * @param o1    被除数
   * @param o2    除数
   * @param scale 保留小数点位数
   * @return 两数之商
   */
  public static String div(Object o1, Object o2, int scale) throws Exception {
    if (scale < 0) {
      throw new IllegalArgumentException("scale必须大于或者等于0");
    }
    if (ZERO.equals(objToString(o2))){
      throw new IllegalArgumentException("o2传入数值不能是0");
    }
    if (o1 instanceof String && o2 instanceof String) {
      // o1和o2均是字符串类型
      return objToString(new BigDecimal(objToString(o1)).divide(new BigDecimal(objToString(o2)),scale,RoundingMode.HALF_UP));
    } else if (o1 instanceof Long && o2 instanceof Long) {
      // o1和o2均是Long类型
      return objToString(BigDecimal.valueOf(Long.parseLong(objToString(o1))).divide(BigDecimal.valueOf(Long.parseLong(objToString(o2))),scale,RoundingMode.HALF_UP));
    } else if (o1 instanceof Double && o2 instanceof Double) {
      // o1和o2均是Double类型
      return objToString(BigDecimal.valueOf(Double.parseDouble(objToString(o1))).divide(BigDecimal.valueOf(Double.parseDouble(objToString(o2))),scale,RoundingMode.HALF_UP));
    } else {
      log.error("o1的类型为:{} o2的类型为:{}", objToString(o1.getClass()), objToString(o2.getClass()));
      throw new RuntimeException("o1与o2类型不一致");
    }
  }

  /**
   * obj对象转化为字符串
   *
   * @param obj obj对象
   * @return 字符串
   */
  public static String objToString(Object obj) {
    return String.valueOf(obj);
  }
}
